package informationExtractionSystem;

import java.util.ArrayList;
import java.util.Hashtable;

import database.mediator.MediatorInterface;
import distributedRE.model.Document;
import distributedRE.model.Relation;
import distributedRE.model.Tuple;

public abstract class InformationExtractor {

	public static int USEFUL_VALUE = 1;
	
	public static int USELESS_VALUE = 0;
	
	public static int NOT_DEFINED_VALUE = -1;
	
	private ArrayList<String> alreadyprocessed;
	
	private ArrayList<Long> recentlyProcessed;
	
	private Hashtable<Long,Hashtable<Long, ArrayList<Tuple>>> storedResults;
	
	private Hashtable<Long,Hashtable<Long, ArrayList<Tuple>>> cachedResults;

	protected MediatorInterface mI;

	private String Id;
	
	public InformationExtractor(String Id, MediatorInterface mI){
		
		this.mI = mI;
		
		alreadyprocessed = mI.getProcessedDocuments(Id);
		
		storedResults = new Hashtable<Long, Hashtable<Long,ArrayList<Tuple>>>();
		
		cachedResults = new Hashtable<Long, Hashtable<Long,ArrayList<Tuple>>>();
		
		recentlyProcessed = new ArrayList<Long>();	
		
		this.Id = Id;
		
	}
	
	public ArrayList<Tuple> process(Relation r, Document document) {
		
		if (wasprocessed(document)){
			
			return getStoredTuples(r,document);
		
		}
		
		ArrayList<Tuple> tuples =  extractTuples(document);
		
		recentlyProcessed.add(new Long(document.getId()));
		
		storeResults(r,document,tuples);
		
		return tuples;
		
	}

	protected ArrayList<Tuple> getStoredTuples(Relation r, Document document) {
		
		Hashtable<Long, ArrayList<Tuple>> st = storedResults.get(r.getId());
		
		if (st == null){
			st = new Hashtable<Long, ArrayList<Tuple>>();
			storedResults.put(r.getId(), st);
		}
		
		ArrayList<Tuple> tuples = st.get(document.getId());
		
		if (tuples != null)
			return tuples;
		
		
		Hashtable<Long, ArrayList<Tuple>> ct = cachedResults.get(r.getId());
		
		if (ct == null){
			ct = new Hashtable<Long, ArrayList<Tuple>>();
			cachedResults.put(r.getId(), ct);
		}
		
		tuples = ct.get(document.getId());
		
		if (tuples == null){
			
			tuples = mI.getStoredTuples(getId(),r.getId(),new Long(document.getId()));
			
			ct.put(document.getId(), tuples);
			
			cachedResults.put(r.getId(), ct);
			
		}
		
		return tuples;
	}

	private void storeResults(Relation r, Document document, ArrayList<Tuple> tuples) {
		
		Hashtable<Long, ArrayList<Tuple>> st = storedResults.get(r.getId());
		
		if (st == null){
			st = new Hashtable<Long, ArrayList<Tuple>>();
		}
		
		st.put(document.getId(), tuples);
		
		storedResults.put(r.getId(), st);
		
	}

	protected abstract ArrayList<Tuple> extractTuples(Document document);
	//Store internally that for this IE is useful...
	
	private boolean wasprocessed(Document document) {
		
		if (recentlyProcessed.contains(document.getId()))
			return true;
			
		if (alreadyprocessed.contains(document.getId()))
			return true;
		
		return false;
		
	}

	public abstract int isUseful(Relation r, Document document);
		//-1 useless, 0 not-processed, 1 useful.

	public String getId() {
		
		return Id;
		
	}

}
